package org.helios.gwt.remote.rebind;

import java.io.PrintWriter;

import org.helios.gwt.remote.client.Exporter;

import com.google.gwt.core.ext.GeneratorContext;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JGenericType;
import com.google.gwt.core.ext.typeinfo.JParameterizedType;
import com.google.gwt.core.ext.typeinfo.JType;

public class ExporterGenerator extends ExporterImporterGenerator 
{

	@Override
	public String generate(TreeLogger logger, GeneratorContext context, String typeName) throws UnableToCompleteException 
	{
		try
		{
			JClassType exporterType = context.getTypeOracle().getType(typeName);
			JGenericType exporterBaseType = context.getTypeOracle().getType(Exporter.class.getName()).isGenericType();
			JParameterizedType parametrization = exporterType.asParameterizationOf(exporterBaseType);
			JType wrappedType = parametrization.getTypeArgs()[0];
			if (!(wrappedType instanceof JClassType))
				throw new IllegalArgumentException("Wrapped type: " + wrappedType.getQualifiedSourceName() + " is not a class or interface");
			JClassType wrappedClassType = (JClassType) wrappedType;
			String wrappedTypeName = wrappedClassType.getQualifiedSourceName();

			String packageName = exporterType.getPackage().getName();
			String implTypeName = exporterType.getName().replace('.', '_') + "_Impl";

			PrintWriter pw = context.tryCreate(logger, packageName, implTypeName);

			if (pw != null) 
			{
				// class (public Impl extends JSObj impl ConcreteExporter)
				pw.append("package ").append(packageName).append(';');
				pw.println();
				pw.append("public class ").append(implTypeName)
					.append(" implements ").append(typeName).append(" {");
				pw.println();
				

				String wrapperImplTypeName = createExporterWrapperImplTypeName(wrappedClassType);
				createExporterWrapperImplType(logger, context, wrapperImplTypeName, wrappedClassType);

				// método export
				pw.append("public final ").append(JSO_TYPENAME).append(" export(").append(wrappedTypeName).append(" obj) { ");
				pw.append("   return ").append(EXPORTER_PACKAGE).append(".").append(wrapperImplTypeName).append(".wrap(obj); }").println();

				// class close
				pw.append("}");
				pw.println();
				
				context.commit(logger, pw);			
			}
	
			return packageName + "." + implTypeName;
		}
		catch (Exception e)
		{
			e.printStackTrace();
			throw new UnableToCompleteException();
		}
	}
}
